package com.quik.web.front.service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.quik.common.Constants;
import com.quik.entity.BizAlterWorkerLog;
import com.quik.entity.BizBilled;
import com.quik.entity.BizBilledPayment;
import com.quik.entity.BizBilling;
import com.quik.entity.BizBillingChessItemDto;
import com.quik.entity.BizBillingChessRoom;
import com.quik.entity.BizBillingItem;
import com.quik.entity.BizBillingItemDto;
import com.quik.entity.BizBillingRelatedItem;
import com.quik.entity.BizBillingService;
import com.quik.entity.BizBillingServiceItemDto;
import com.quik.entity.BizInvoice;
import com.quik.entity.DtaProduct;
import com.quik.entity.ProductPrice;
import com.quik.entity.Room;
import com.quik.entity.SysAccount;
import com.quik.entity.SysSystemCode;
import com.quik.entity.DtaToken;
import com.quik.entity.VipAccount;
import com.quik.entity.DtaWorker;
import com.quik.util.CommonUtils;
import com.quik.util.ProductPriceDate;
import com.quik.util.Tools;
import com.quik.web.base.mapper.PubSystemDao;
import com.quik.web.front.mapper.ConsultBillingDao;

/**
 * 功能说明： 接口ConsultBillingService实现类
 * 
 * @author Jenny
 * 
 */
@Service
@SuppressWarnings({ "rawtypes", "unchecked" })
public class ConsultBillingServiceImpl extends ConsultBaseService implements
		ConsultBillingService {

	@Autowired
	private ConsultBillingDao dao;

	@Autowired
	private PubSystemDao systemDao;

	/**
	 * 根据编号及编号类型查询关联的帐单
	 * 
	 * @param itemNo
	 * @param itemType
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findRelateBillingByItemNo(String itemNo, Integer itemType)
			throws Exception {
		List billingList = new ArrayList();
		BizBilling billing = dao.findBillingByRelatedItem(itemNo, itemType);
		if (billing != null) {
			if (billing.getIf_master().equals(BizBilling.MASTER_NO)) {
				// 如果不是主帐单，则查询出主帐单
				billing = dao.findBillingByRelatedItem(billing.getBilling_no(),
						BizBillingRelatedItem.ITEM_TYPE_BILLING);
			}
			List relateBillingList = dao.findRelatedBillingByBillingId(billing
					.getId());
			billingList.add(billing);
			if (relateBillingList != null && !relateBillingList.isEmpty())
				billingList.addAll(relateBillingList);
		}

		return billingList;
	}

	/**
	 * 根据帐单ID查询所有帐单关联的房间
	 * 
	 * @param billingIdList
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findRelateRoomByBillingId(List billingList) throws Exception {
		List roomAllList = new ArrayList();
		if (billingList != null && !billingList.isEmpty()) {
			for (Iterator its = billingList.iterator(); its.hasNext();) {
				BizBilling billing = (BizBilling) its.next();
				List roomList = dao.findRelateRoomByBillingId(billing.getId());
				if (roomList != null && !roomList.isEmpty())
					roomAllList.addAll(roomList);
			}
		}

		return roomAllList;
	}

	/**
	 * 根据帐单ID查询所有帐单关联的手牌
	 * 
	 * @param billingList
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findRelateTokenByBillingId(List billingList) throws Exception {
		List tokenAllList = new ArrayList();
		for (Iterator its = billingList.iterator(); its.hasNext();) {
			BizBilling billing = (BizBilling) its.next();
			List tokenList = dao.findRelateTokenByBillingId(billing.getId());
			if (tokenList != null && !tokenList.isEmpty())
				tokenAllList.addAll(tokenList);
		}

		return tokenAllList;
	}

	/**
	 * 根据帐单ID查询所有帐单关联的棋牌类消费
	 * 
	 * @param billingList
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findChessConsumeByBillingId(List billingList) throws Exception {
		List chessAllList = new ArrayList();
		for (Iterator its = billingList.iterator(); its.hasNext();) {
			BizBilling billing = (BizBilling) its.next();
			List chessList = dao.findChessConsumeByBillingId(billing.getId());
			if (chessList != null && !chessList.isEmpty())
				chessAllList.addAll(chessList);
		}

		return chessAllList;
	}

	/**
	 * 根据帐单ID查询所有帐单关联的服务类消费
	 * 
	 * @param billingList
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findServiceConsumeByBillingId(List billingList)
			throws Exception {
		List serviceAllList = new ArrayList();
		for (Iterator its = billingList.iterator(); its.hasNext();) {
			BizBilling billing = (BizBilling) its.next();
			List serviceList = dao.findServiceConsumeByBillingId(billing
					.getId());
			if (serviceList != null && !serviceList.isEmpty())
				serviceAllList.addAll(serviceList);
		}

		return serviceAllList;
	}

	/**
	 * 根据帐单ID查询所有帐单关联的非棋牌及非服务类消费
	 * 
	 * @param billingList
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findOtherConsumeByBillingId(List billingList) throws Exception {
		List otherAllList = new ArrayList();
		for (Iterator its = billingList.iterator(); its.hasNext();) {
			BizBilling billing = (BizBilling) its.next();
			List otherList = dao.findOtherConsumeByBillingId(billing.getId());
			if (otherList != null && !otherList.isEmpty())
				otherAllList.addAll(otherList);
		}

		return otherAllList;
	}

	/**
	 * 房间或手牌是否有效
	 * 
	 * @param roomNo
	 * @param tokenNo
	 * @return
	 * @throws Exception
	 */
	@Override
	public boolean isValid(String roomNo, String tokenNo) throws Exception {
		BizBillingRelatedItem roomItem = null;
		BizBillingRelatedItem tokenItem = null;

		if (roomNo != null && roomNo.trim().length() > 0) {
			roomItem = dao.findBillingRelateItemByTermNo(roomNo,
					BizBillingRelatedItem.ITEM_TYPE_ROOM);
		}

		if (tokenNo != null && tokenNo.trim().length() > 0) {
			tokenItem = dao.findBillingRelateItemByTermNo(tokenNo,
					BizBillingRelatedItem.ITEM_TYPE_TOKEN);
		}

		if (roomItem != null || tokenItem != null)
			return true;
		else
			return false;
	}

	/**
	 * 消费 1.更新biz_billing_item 2.如果是棋牌类，更新 biz_billing_chess_room
	 * 3.如果是服务类，更新biz_billing_service
	 * 
	 * @param productNo
	 *            规则：productNo;service;chess;price;qty
	 * @param roomNo
	 * @param tokenNo
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public Integer consume(String[] productNo, String roomNo, String tokenNo,
			String staffNo) throws Exception {
		Integer billingId = 0;
		if (roomNo != null && roomNo.trim().length() > 0)
			billingId = dao.findBillingIdByItemNo(roomNo,
					BizBillingRelatedItem.ITEM_TYPE_ROOM);
		else if (tokenNo != null && tokenNo.trim().length() > 0) {
			if (billingId == null || billingId == 0)
				billingId = dao.findBillingIdByItemNo(tokenNo,
						BizBillingRelatedItem.ITEM_TYPE_TOKEN);
		}

		BizBillingItem item = new BizBillingItem();
		item.setBilling_id(billingId);
		item.setCrt_user(staffNo);
		item.setIs_free(BizBillingItem.STATUS_NO);
		item.setIs_subtract(BizBillingItem.STATUS_NO);
		item.setStatus(BizBillingItem.STATUS_ORDER);

		if (roomNo != null && roomNo.trim().length() > 0) {
			billingId = dao.findBillingIdByItemNo(roomNo,
					BizBillingRelatedItem.ITEM_TYPE_ROOM);
			item.setRoom_no(roomNo);
		} else if (tokenNo != null && tokenNo.trim().length() > 0) {
			billingId = dao.findBillingIdByItemNo(tokenNo,
					BizBillingRelatedItem.ITEM_TYPE_TOKEN);
			item.setToken_no(tokenNo);
		}
		// productNo;service;chess;price;qty
		for (String product : productNo) {
			item.setId(null);
			String[] str = product.split(";");
			item.setProduct_no(str[0]);
			item.setQty(Integer.parseInt(str[4]));
			item.setPrice(Integer.parseInt(str[3]));
			// 只有服务类需要单独出来
			if (str[1].equals(DtaProduct.OPTION_FOR_YES)) {
				// for(int i = 0; i<Integer.valueOf(str[4]);i++){
				// item.setId(null);
				// item.setQty(1);
				dao.addBizBillingItem(item);
				dao.addBizBillingService(getBizBillingService(item.getId(),
						staffNo));
				// }
			} else {
				dao.addBizBillingItem(item);

				if (str[2].equals(DtaProduct.OPTION_FOR_YES)) {
					List systemList = systemDao.findSystemCodeBySection(Tools
							.getSection(BizBillingChessRoom.TABLE_NAME,
									Constants.SYSTEM_CODE_CALCMODE));
					SysSystemCode systemCode = (SysSystemCode) systemList
							.get(0);
					dao.addBizBillingChessRoom(getBizBillingChessRoom(
							item.getId(),
							Integer.parseInt(systemCode.getName()), staffNo));
				}
			}
		}
		return billingId;

	}

	@Override
	public Integer addBillingItemByBillingId(Integer billingId,
			String[] productNos, Integer[] qtys, String roomNo, String tokenNo,
			String staffNo) throws Exception {
		for (int i = 0; i < productNos.length; i++) {
			String productNo = productNos[i];
			Integer qty = qtys[i];
			DtaProduct product = this.getProductByNo(productNo);
			if (DtaProduct.OPTION_FOR_YES.equals(product.getIf_need_worker())) {
				for (int j = 0; j < qty; j++) {
					BizBillingItem item = getBizBillingItem(product, tokenNo,
							roomNo, 1, staffNo);
					item.setBilling_id(billingId);
					dao.addBizBillingItem(item);
					if (product.getNum_of_worker() == null
							|| product.getNum_of_worker() < 1) {
						BizBillingService billingService = this
								.getBizBillingService(item.getId(), staffNo,
										product);
						dao.addBizBillingService(billingService);
					} else {
						for (int k = 0; k < product.getNum_of_worker(); k++) {
							BizBillingService billingService = this
									.getBizBillingService(item.getId(),
											staffNo, product);
							dao.addBizBillingService(billingService);
						}
					}
				}
			} else if (DtaProduct.OPTION_FOR_YES
					.equals(product.getIf_chess_room())) {

				for (int j = 0; j < qty; j++) {
					BizBillingItem item = getBizBillingItem(product, tokenNo,
							roomNo, 1, staffNo);
					item.setBilling_id(billingId);
					dao.addBizBillingItem(item);
				}

			} else {
				BizBillingItem item = getBizBillingItem(product, tokenNo,
						roomNo, qty, staffNo);
				item.setBilling_id(billingId);
				dao.addBizBillingItem(item);
			}
		}
		return billingId;
	}

	/**
	 * 查询轮钟方式
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findTurnTypeList() throws Exception {
		List list = systemDao.findSystemCodeBySection(Tools.getSection(
				BizBillingService.TABLE_NAME, Constants.SYSTEM_CODE_TURNTYPE));
		return list;
	}

	/**
	 * 分配技师 1.更新biz_billing_item的状态 2.更新biz_billing_service表中的状态、技师等信息
	 * 3.更新dta_worker表的状态
	 * 
	 * @param itemId
	 * @param subItemId
	 * @param workerNo
	 * @param turnType
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void service(Integer itemId, Integer subItemId, String workerNo,
			String turnType, String staffNo) throws Exception {
		dao.updateBizBillingItemStatusById(itemId,
				BizBillingItem.STATUS_ALLOCATION, staffNo);

		dao.updateBizBillingServiceInfoById(subItemId,
				BizBillingItem.STATUS_ALLOCATION, workerNo, turnType, staffNo);

		dao.updateWorkerStatusByWorkerNo(workerNo, DtaWorker.STATUS_SERVICE,
				staffNo);
	}

	/**
	 * 起钟 1.更新biz_billing_item的状态为起钟，
	 * 2.更新biz_billing_service或biz_billing_chess_room的起钟时间和状态
	 * 
	 * @param itemId
	 * @param subItemId
	 * @param service
	 * @param chessRoom
	 * @param staffNo
	 * @return 返回起钟的时间
	 * @throws Exception
	 */
	public String start(Integer itemId, Integer subItemId, String service,
			String chessRoom, String staffNo) throws Exception {
		Date startTime = new Date(System.currentTimeMillis());
		if (service.equals(DtaProduct.OPTION_FOR_YES)) {
			dao.updateBizBillingItemStatusById(itemId,
					BizBillingItem.STATUS_SERVIE, staffNo);

			DtaProduct product = dao.findProductByItemId(itemId);
			Integer numOfHour = product.getNum_of_hour();
			Date planEndTime = Tools.calcDateAfter(startTime, numOfHour);
			dao.updateBizBillingServiceStartTime(subItemId,
					BizBillingItem.STATUS_SERVIE, startTime, planEndTime,
					staffNo);

		}

		if (chessRoom.equals(DtaProduct.OPTION_FOR_YES)) {
			dao.updateBizBillingItemStatusById(itemId,
					BizBillingItem.STATUS_USED, staffNo);

			dao.updateBizBillingChessRoomStartTime(subItemId,
					BizBillingItem.STATUS_USED, startTime, staffNo);
		}

		return Tools.date2String(startTime);
	}

	@Override
	public String startByItemId(Integer billingItemId, String staffNo)
			throws Exception {
		Date startTime = new Date(System.currentTimeMillis());
		BizBillingItem billingItem = this.dao
				.getBizBillingItemByItemId(billingItemId);
		DtaProduct product = this.dao.getProductByNo(billingItem.getProduct_no());
		if (DtaProduct.OPTION_FOR_YES
				.equalsIgnoreCase(product.getIf_need_worker())) {
			dao.updateBizBillingItemServeStatusById(billingItemId,
					BizBillingItem.BILLING_ITEM_SERVE_STATUS_SERVING, staffNo);

			Integer numOfHour = product.getNum_of_hour();
			Date planEndTime = Tools.calcDateAfter(startTime, numOfHour);
			dao.updateBizBillingServiceStartTime(billingItemId,
					BizBillingService.BILLING_SERVICE_STATUS_NORMAL, startTime,
					planEndTime, staffNo);

		} else if (DtaProduct.OPTION_FOR_YES.equalsIgnoreCase(product
				.getIf_chess_room())) {
			dao.updateBizBillingItemServeStatusById(billingItemId,
					BizBillingItem.BILLING_ITEM_ROOM_STATUS_READY, staffNo);

			dao.updateBizBillingChessRoomStartTime(billingItemId,
					BizBillingChessRoom.BILLING_ROOM_STATUS_NORMAL, startTime,
					staffNo);
		}

		return Tools.date2String(startTime);
	}

	/**
	 * 授权验证（待扩展）
	 * 
	 * @param password
	 * @return
	 * @throws Exception
	 */
	@Override
	public boolean isAuth(String operateAccount, String password)
			throws Exception {
		return true;
	}

	/**
	 * 是否允许撤单 （只有取消状态不允许撤单）
	 * 
	 * @param itemId
	 * @return 如果允许撤单返回true,否则返回false
	 * @throws Exception
	 */
	@Override
	public boolean isOrder(Integer itemId) throws Exception {
		BizBillingItem item = dao.getBizBillingItemByItemId(itemId);
		if (item.getStatus().equals(BizBillingItem.STATUS_CANCEL))
			return false;
		else
			return true;
	}

	/**
	 * 撤单 1.更新biz_billing_item状态 2.服务类，更新biz_billing_service状态，更新dta_worker状态
	 * 3.棋牌类，更新biz_billing_chess_room状态
	 * 
	 * @param itemId
	 * @param subItemId
	 * @param service
	 * @param chess
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void cancelOrder(Integer itemId, Integer subItemId, String service,
			String chess, String staffNo) throws Exception {
		dao.updateBizBillingItemStatusById(itemId,
				BizBillingItem.STATUS_CANCEL, staffNo);

		if (service.equals(DtaProduct.OPTION_FOR_YES)) {
			dao.updateBizBillingServiceStatus(subItemId,
					BizBillingItem.STATUS_CANCEL, staffNo);

			// 查询技师编号
			BizBillingService billingService = dao
					.getBizBillingServiceById(subItemId);
			if (billingService.getWorker_no() != null
					&& billingService.getWorker_no().length() > 0)
				dao.updateWorkerStatusByWorkerNo(billingService.getWorker_no(),
						DtaWorker.STATUS_FREE, staffNo);
		}

		if (chess.equals(DtaProduct.OPTION_FOR_YES)) {
			dao.updateBizBillingChessRoomStatus(subItemId,
					BizBillingItem.STATUS_CANCEL, staffNo);
		}
	}

	/**
	 * 落钟 1.更新biz_billing_item的状态为结束，
	 * 2.更新biz_billing_service或biz_billing_chess_room的结束时间和状态 3.若是服务类，更新技师状态为空闲
	 * 
	 * @param itemId
	 * @param subItemId
	 * @param service
	 * @param chessRoom
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public String end(Integer itemId, Integer subItemId, String service,
			String chessRoom, String staffNo) throws Exception {
		Date endTime = new Date(System.currentTimeMillis());
		dao.updateBizBillingItemStatusById(itemId, BizBillingItem.STATUS_END,
				staffNo);

		if (service.equals(DtaProduct.OPTION_FOR_YES)) {
			dao.updateBizBillingServiceEndTime(subItemId,
					BizBillingItem.STATUS_END, endTime, staffNo);
			// 查询技师编号
			BizBillingService billingService = dao
					.getBizBillingServiceById(subItemId);
			if (billingService.getWorker_no() != null
					&& billingService.getWorker_no().length() > 0)
				dao.updateWorkerStatusByWorkerNo(billingService.getWorker_no(),
						DtaWorker.STATUS_FREE, staffNo);
		}

		if (chessRoom.equals(DtaProduct.OPTION_FOR_YES)) {
			dao.updateBizBillingChessRoomEndTime(subItemId,
					BizBillingItem.STATUS_END, endTime, staffNo);
		}

		return Tools.date2String(endTime);
	}

	/**
	 * 反落钟
	 * 
	 * @param itemId
	 * @param subItemId
	 * @param service
	 * @param chessRoom
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void reverseEnd(Integer itemId, Integer subItemId, String service,
			String chessRoom, String staffNo) throws Exception {
		if (chessRoom.equals(DtaProduct.OPTION_FOR_YES)) {
			dao.updateBizBillingItemStatusById(itemId,
					BizBillingItem.STATUS_USED, staffNo);
			dao.updateBizBillingChessRoomEndTime(subItemId,
					BizBillingItem.STATUS_USED, null, staffNo);
		}

		if (service.equals(DtaProduct.OPTION_FOR_YES)) {
			dao.updateBizBillingItemStatusById(itemId,
					BizBillingItem.STATUS_SERVIE, staffNo);
			dao.updateBizBillingServiceEndTime(subItemId,
					BizBillingItem.STATUS_SERVIE, null, staffNo);

			BizBillingService billingService = dao
					.getBizBillingServiceById(subItemId);
			if (billingService.getWorker_no() != null
					&& billingService.getWorker_no().length() > 0)
				dao.updateWorkerStatusByWorkerNo(billingService.getWorker_no(),
						DtaWorker.STATUS_SERVICE, staffNo);
		}
	}

	/**
	 * 退钟（去掉技师以及轮钟方式, 更新技师的状态）
	 * 
	 * @param subItemId
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void endCall(Integer subItemId, String staffNo) throws Exception {
		BizBillingService billingService = dao
				.getBizBillingServiceById(subItemId);
		if (billingService.getWorker_no() != null
				&& billingService.getWorker_no().length() > 0)
			dao.updateWorkerStatusByWorkerNo(billingService.getWorker_no(),
					DtaWorker.STATUS_FREE, staffNo);

		dao.updateBizBillingServiceInfoById(subItemId,
				BizBillingItem.STATUS_SERVIE, null, null, staffNo);
	}

	/**
	 * 更换技师 1.更新biz_billing_service的技师 2.更新新、旧技师的状态 3.新增更换技师记录
	 * 
	 * @param srcWorkerNo
	 * @param workerNo
	 * @param itemId
	 * @param subItemId
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void exchangeWorker(String srcWorkerNo, String workerNo,
			Integer itemId, Integer subItemId, String staffNo) throws Exception {
		BizBillingService billingService = dao
				.getBizBillingServiceById(subItemId);

		dao.updateBizBillingServiceInfoById(subItemId,
				billingService.getStatus(), workerNo,
				billingService.getTurn_type(), staffNo);

		dao.updateWorkerStatusByWorkerNo(srcWorkerNo, DtaWorker.STATUS_FREE,
				staffNo);
		dao.updateWorkerStatusByWorkerNo(workerNo, DtaWorker.STATUS_SERVICE,
				staffNo);

		BizAlterWorkerLog workerLog = new BizAlterWorkerLog();
		workerLog.setBilling_item_id(itemId);
		workerLog.setBilling_service_id(subItemId);
		workerLog.setCrt_user(staffNo);
		workerLog.setSrc_worker_no(srcWorkerNo);
		workerLog.setWorker_no(workerNo);
		dao.addAlterWorkerLog(workerLog);
	}

	/**
	 * 根据手牌、房间以及帐单查询可供关联的帐单 只有未发生关联的主帐单可以进行关联（主帐单一旦发生关联，将不能被关联到其它帐单上）
	 * 
	 * @param itemNo
	 * @param itemType
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findRelateBilling(String itemNo, Integer itemType)
			throws Exception {
		// 1.查询所属已有关联的主帐单(返回帐单ID)
		List relatedBillingList = dao.findRelatedBillingList();

		// 2.查询所有房间、手牌关联的活动主帐单
		String billingNo = null;
		if (itemType == null
				|| itemType == BizBillingRelatedItem.ITEM_TYPE_BILLING)
			billingNo = itemNo;

		List relatingBillingList = dao.findRelatingBillingList(itemType != null
				&& itemType == BizBillingRelatedItem.ITEM_TYPE_BILLING ? null
				: itemNo, billingNo, itemType);

		if (relatingBillingList != null && !relatingBillingList.isEmpty()) {
			if (relatedBillingList != null && !relatedBillingList.isEmpty()) {
				for (Iterator its = relatingBillingList.iterator(); its
						.hasNext();) {
					BizBillingRelatedItem item = (BizBillingRelatedItem) its
							.next();
					for (int i = 0; i < relatedBillingList.size(); i++) {
						Integer billingId = (Integer) relatedBillingList.get(i);
						if (item.getBilling_id().intValue() == billingId
								.intValue()) {
							its.remove();
							break;
						}
					}
				}
			}
		}

		return relatingBillingList;
	}

	/**
	 * 根据ITEM编号及类型查询未结帐帐单
	 * 
	 * @param itemNo
	 * @return
	 */
	@Override
	public BizBilling getRelateBilling(String itemNo, Integer itemType)
			throws Exception {
		if (itemType.intValue() == BizBillingRelatedItem.ITEM_TYPE_BILLING) {
			BizBilling billing = dao.getBillingByBillingNo(itemNo,
					BizBilling.STATUS_ACTIVE);
			return billing;
		} else {
			BizBilling billing = dao.getRelateBilling(itemNo, itemType);
			return billing;
		}
	}

	/**
	 * 根据ITEM编号及类型查询帐单
	 * 
	 * @param itemNo
	 * @return
	 */
	@Override
	public BizBilling getRelateBizBilling(String itemNo, Integer itemType)
			throws Exception {
		if (itemType.intValue() == BizBillingRelatedItem.ITEM_TYPE_BILLING) {
			BizBilling billing = dao.getBillingByBillingNo(itemNo, null);
			return billing;
		} else {
			BizBilling billing = dao.getRelateBilling(itemNo, itemType);
			return billing;
		}
	}

	/**
	 * 判断帐单是否是主帐单
	 * 
	 * @param bizBilling
	 * @return 主帐单则返回true， 否则返回false
	 * @throws Exception
	 */
	@Override
	public boolean isMasterBilling(BizBilling bizBilling) throws Exception {
		if (bizBilling != null
				&& bizBilling.getIf_master().intValue() == BizBilling.MASTER_YES)
			return true;
		else
			return false;
	}

	/**
	 * 关联帐单 (1.新增biz_billing_related_item表 2.修改biz_billing为非主帐单)
	 * 
	 * @param bizBilling
	 * @param billingIds
	 * @param billingNos
	 * @throws Exception
	 */
	@Override
	public void relateBilling(BizBilling bizBilling, Integer[] billingIds,
			String[] billingNos, String staffNo) throws Exception {
		BizBillingRelatedItem item = new BizBillingRelatedItem();
		item.setBilling_id(bizBilling.getId());
		item.setItem_type(BizBillingRelatedItem.ITEM_TYPE_BILLING);
		item.setCrt_user(staffNo);

		for (String billingNo : billingNos) {
			if (!billingNo.equals(bizBilling.getBilling_no())) { // 自己不能关联自己
				item.setItem_no(billingNo);
				dao.addBizBillingRelatedItem(item);
				dao.updateBizBillingType(billingNo, staffNo);
			}
		}
	}

	/**
	 * 根据帐单编号查询帐单（包括关联的所有帐单）
	 * 
	 * @param billingNo
	 * @return
	 * @throws Exception
	 */
	public List findRelateBillingByBillingNo(String billingNo) throws Exception {
		List billingList = new ArrayList();
		BizBilling billing = dao.getBillingByBillingNo(billingNo,
				BizBilling.STATUS_ACTIVE);
		if (billing != null) {
			if (billing.getIf_master().equals(BizBilling.MASTER_NO)) {
				// 如果不是主帐单，则查询出主帐单
				billing = dao.findBillingByRelatedItem(billing.getBilling_no(),
						BizBillingRelatedItem.ITEM_TYPE_BILLING);
			}
			List relateBillingList = dao.findRelatedBillingByBillingId(billing
					.getId());
			billingList.add(billing);
			if (relateBillingList != null && !relateBillingList.isEmpty())
				billingList.addAll(relateBillingList);
		}

		return billingList;
	}

	/**
	 * 判断要转移的帐号是否有效
	 * 
	 * @param billingType
	 * @param transferNo
	 * @return
	 * @throws Exception
	 */
	@Override
	public boolean isValidBilling(Integer billingType, String transferNo)
			throws Exception {
		BizBilling billing = null;
		if (billingType == BizBillingRelatedItem.ITEM_TYPE_BILLING)
			billing = dao.getBillingByBillingNo(transferNo,
					BizBilling.STATUS_ACTIVE);
		else
			billing = dao.findBillingByRelatedItem(transferNo, billingType);

		if (billing == null)
			return false;
		else
			return true;
	}

	/**
	 * 转移单项帐单
	 * 
	 * @param itemId
	 * @param billingType
	 * @param transferNo
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void transfer(Integer itemId, Integer billingType,
			String transferNo, String staffNo) throws Exception {
		BizBilling billing = null;
		if (billingType == BizBillingRelatedItem.ITEM_TYPE_BILLING)
			billing = dao.getBillingByBillingNo(transferNo,
					BizBilling.STATUS_ACTIVE);
		else
			billing = dao.findBillingByRelatedItem(transferNo, billingType);

		if (billing != null) {
			String billingNo = dao.getBillingNoByBizBillingItemId(itemId);
			dao.updateBizBillingItemTransfer(itemId, billing.getId(), billingNo
					+ Constants.TRANSFER_REMARK, staffNo);
		}
	}

	/**
	 * 开发票
	 * 
	 * @param invoiceNo
	 * @param invoiceTitle
	 * @param invoiceAmount
	 * @param actualAmount
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void addInvoice(String invoiceNo, String invoiceTitle,
			String invoiceAmount, String actualAmount, String staffNo)
			throws Exception {
		BizInvoice invoice = new BizInvoice();
		invoice.setInvoice_no(invoiceNo);
		invoice.setTitle(invoiceTitle);
		invoice.setActual_amount(Tools.getAmount(actualAmount));
		invoice.setInvoice_amount(Tools.getAmount(invoiceAmount));
		invoice.setCrt_user(staffNo);

		dao.addInvoice(invoice);
	}

	/**
	 * 设置营业日(1.设置biz_billing_item中的billing_business_day
	 * 2.设置biz_billed表中的billed_business_day)
	 * 
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void updateBusinessDay(String staffNo) throws Exception {
		String businessDay = Tools.getNowDay("yyyyMMdd");
		dao.updateBizBillingItemBusinessDay(businessDay, staffNo);
		dao.updateBizBilledBusinessDay(businessDay, staffNo);
	}

	/**
	 * 取消帐单（全部）
	 * 
	 * @param billingIds
	 *            格式：billingId;billingId;
	 * @param staffNo
	 * @throws Exception
	 */
	public void cancelAll(String billingIds, String staffNo) throws Exception {
		for (String billingId : billingIds.split(";")) {
			// 更新biz_billing的状态为取消
			dao.updateBizBillingStatusByBillingId(BizBilling.STATUS_CANCELLED,
					Integer.parseInt(billingId), staffNo);
			// 将对应billingId的房间或者手牌状态更新为空闲
			dao.updateRoomStatusByBillingId(Room.ROOM_STATUS_FREE,
					Integer.parseInt(billingId), staffNo);
			dao.updateTokenStatusByBillingId(DtaToken.TOKEN_STATUS_FREE,
					Integer.parseInt(billingId), staffNo);
			// 更新biz_billing_item的状态为取消
			dao.updateBizBillingItemStatusByBillingId(
					BizBillingItem.STATUS_CANCEL, Integer.parseInt(billingId),
					staffNo);
			// 更新biz_billing_chess_room的状态为取消
			dao.updateBizBillingChessRoomStatusByBillingId(
					BizBillingItem.STATUS_CANCEL, Integer.parseInt(billingId),
					staffNo);
			// 更新biz_billing_service的状态为取消
			dao.updateBizBillingServiceStatusByBillingId(
					BizBillingItem.STATUS_CANCEL, Integer.parseInt(billingId),
					staffNo);
			// 更新worker的状态为空闲
			dao.updateWorkerStatusByBillingId(DtaWorker.STATUS_FREE,
					Integer.parseInt(billingId), staffNo);

		}
	}

	/**
	 * 查询未结帐帐单
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findActiveBillingList() throws Exception {
		List billingList = dao.findActiveBillingList();
		return billingList;
	}

	/**
	 * 根据帐单ID查询所有的帐单（包括包含的主帐单、关联帐单） 备注：需要考虑ID，有可能就是主帐单与其从帐单
	 * 
	 * @param billingIds
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findAllBillingListByBillingId(String[] billingNos)
			throws Exception {
		List billingAllList = new ArrayList();
		for (String billingNo : billingNos) {
			if (!billingAllList.isEmpty()) {
				if (checkSameBillingNo(billingAllList, billingNo)) {
					continue;
				}
			}

			List billingList = findRelateBillingByBillingNo(billingNo);
			if (billingList != null && !billingList.isEmpty())
				billingAllList.addAll(billingList);
		}
		return billingAllList;
	}

	/**
	 * 检查列表中是否有重复的帐单
	 * 
	 * @param billingList
	 * @param billingNo
	 * @return 如果有相同的，返回true，否则返回false
	 */
	private boolean checkSameBillingNo(List billingList, String billingNo) {
		boolean flag = false;
		for (Iterator its = billingList.iterator(); its.hasNext();) {
			BizBilling billing = (BizBilling) its.next();
			if (billing.getBilling_no().equals(billingNo)) {
				flag = true;
				break;
			}
		}

		return flag;
	}

	/**
	 * 查询付款方式
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findPaymentTypeList() throws Exception {
		List paymentTypeList = systemDao.findSystemCodeBySection(Tools
				.getSection(BizBilledPayment.TABLE_NAME,
						Constants.SYSTEM_CODE_PAYMENTTYPE));
		return paymentTypeList;
	}

	/**
	 * 根据VIP号查询VIP帐户
	 * 
	 * @param vipCard
	 * @return
	 * @throws Exception
	 */
	@Override
	public VipAccount getVipAccount(String vipCard) throws Exception {
		VipAccount vipAccount = dao.getVipAccount(vipCard);
		return vipAccount;
	}

	/**
	 * 与当前日期比较大小
	 * 
	 * @param date
	 * @return 0 表示等于当前日期， 1表示大于日期，-1表示小于当前日期
	 * @throws Exception
	 */
	@Override
	public int compareTime(Date date) throws Exception {
		Date now = new Date(System.currentTimeMillis());

		SimpleDateFormat ft = new SimpleDateFormat("yyyy/MM/dd");
		Date date1 = ft.parse(ft.format(date));
		Date now1 = ft.parse(ft.format(now));

		return date1.compareTo(now1);
	}

	/**
	 * 查询计价时间段类型
	 * 
	 * @return
	 * @throws Exception
	 */
	public int getProductPriceType() throws Exception {
		List list = systemDao.findSystemCodeBySection(Tools
				.getSection(ProductPrice.TABLE_NAME,
						Constants.SYSTEM_CODE_PRODUCTPRICETYPE));
		return Integer.parseInt(((SysSystemCode) list.get(0)).getName());
	}

	/**
	 * 计算服务类的时间、总价、实际价 实际价是以实际为准
	 * 
	 * @param serviceList
	 * @throws Exception
	 */
	@Override
	public void calcServicePrice(List serviceList, Integer productPriceType)
			throws Exception {
		if (serviceList != null && !serviceList.isEmpty()) {

			for (Iterator its = serviceList.iterator(); its.hasNext();) {
				BizBillingServiceItemDto serviceDto = (BizBillingServiceItemDto) its
						.next();
				// 如果取消，则价格直接为0
				if (serviceDto.getStatus().equals(BizBillingItem.STATUS_CANCEL)) {
					serviceDto.setTotalPrice(0);
					serviceDto.setActualPrice(0);
					serviceDto.setVipPrice(0);
				} else {
					if (serviceDto.getStatus()
							.equals(BizBillingItem.STATUS_END)) {
						// 初始化
						serviceDto.setTotalPrice(0);
						serviceDto.setActualPrice(0);
						serviceDto.setVipPrice(0);

						// 查询对应的产品
						DtaProduct product = dao.getProductByNo(serviceDto
								.getProductNo());
						// 直接用product中的价格来进行计算
						// serviceDto.setQty(getHour(serviceDto.getStartTime(),
						// serviceDto.getEndTime(), product.getMin_of_buff()));
						serviceDto.setTotalPrice(serviceDto.getQty()
								* product.getPrice());
						serviceDto.setVipPrice(serviceDto.getQty()
								* product.getVip_price());
						serviceDto.setActualPrice(serviceDto.getQty()
								* product.getPrice());

					}
				}
			}
		}
	}

	/**
	 * 计算时间（小时）
	 * 
	 * @param startTime
	 * @param endTime
	 * @param buffTime
	 *            缓冲时间
	 * @return
	 * @throws Exception
	 */
	private int getHour(String startTime, String endTime, Integer buffTime)
			throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		// 计算时间段
		int minute = (int) Tools.compareDate(sdf.parse(startTime),
				sdf.parse(endTime));
		int hour = minute / 60;
		if (buffTime != null) {
			if (minute % 60 > buffTime)
				hour += 1;
		}
		return hour;
	}

	/**
	 * 根据产品编号查询编号
	 * 
	 * @param productNo
	 * @return
	 * @throws Exception
	 */
	@Override
	public DtaProduct getProductByNo(String productNo) throws Exception {
		DtaProduct product = dao.getProductByNo(productNo);
		return product;
	}

	/**
	 * 计算棋牌的时间、总价、实际价 实际价是以实际为准
	 * 
	 * @param chessList
	 * @param productPriceType
	 * @throws Exception
	 */
	@Override
	public void calcChessPrice(List chessList, Integer productPriceType)
			throws Exception {
		if (chessList != null && !chessList.isEmpty()) {

			for (Iterator its = chessList.iterator(); its.hasNext();) {
				BizBillingChessItemDto chessDto = (BizBillingChessItemDto) its
						.next();
				// 如果取消，则价格直接为0
				if (chessDto.getStatus().equals(BizBillingItem.STATUS_CANCEL)) {
					chessDto.setTotalPrice(0);
					chessDto.setActualPrice(0);
					chessDto.setVipPrice(0);
				} else {
					if (chessDto.getStatus().equals(BizBillingItem.STATUS_END)) {
						// 初始化
						chessDto.setTotalPrice(0);
						chessDto.setActualPrice(0);
						chessDto.setVipPrice(0);

						// 查询对应的产品
						DtaProduct product = dao.getProductByNo(chessDto
								.getProductNo());

						List productPriceList = dao
								.findProductPriceListByProductNo(
										chessDto.getProductNo(),
										productPriceType);
						if (productPriceList != null
								&& !productPriceList.isEmpty()) {
							ProductPriceDate priceDate = null;
							int tempTime = 0; // 临时需要记录时间;
							for (int i = 0; i < productPriceList.size(); i++) {

								ProductPrice productPrice = (ProductPrice) productPriceList
										.get(i);

								if (productPriceType == ProductPrice.TIME_METHOD) {
									if (i == 0) { // 计算时间段
										priceDate = Tools
												.configProductTime(
														productPrice
																.getTake_eff_start_time() == null ? "800"
																: productPrice
																		.getTake_eff_start_time(),
														productPrice
																.getTake_eff_end_time() == null ? "1800"
																: productPrice
																		.getTake_eff_end_time(),
														chessDto.getStartTime(),
														chessDto.getEndTime(),
														product.getMin_of_buff() == null ? 0
																: product
																		.getMin_of_buff());
										chessDto.setQty(priceDate.getInHour()
												+ priceDate.getOutHour());
									}

									if (productPrice.getSeq() == 1
											&& productPrice
													.getTake_eff_start_time() == null) {
										// 为空，直接计算后跳出本次循环
										chessDto.setQty(priceDate.getInHour()
												+ priceDate.getOutHour());
										chessDto.setTotalPrice(chessDto
												.getQty()
												* productPrice.getPrice());
										chessDto.setVipPrice(chessDto.getQty()
												* productPrice.getVip_price());
										chessDto.setActualPrice(chessDto
												.getQty()
												* productPrice.getPrice());
										break;
									} else {
										if (productPrice.getSeq() == 1) {
											// 第一次计算
											if (priceDate.getInHour() > 0) {
												chessDto.setTotalPrice(priceDate
														.getInHour()
														* productPrice
																.getPrice());
												chessDto.setVipPrice(priceDate
														.getInHour()
														* productPrice
																.getVip_price());
												chessDto.setActualPrice(priceDate
														.getInHour()
														* productPrice
																.getPrice());
											}
											if (priceDate.getOutHour() == 0)
												break;
										} else {
											chessDto.setTotalPrice(chessDto
													.getTotalPrice()
													+ priceDate.getOutHour()
													* productPrice.getPrice());
											chessDto.setVipPrice(chessDto
													.getVipPrice()
													+ priceDate.getOutHour()
													* productPrice
															.getVip_price());
											chessDto.setActualPrice(chessDto
													.getActualPrice()
													+ priceDate.getOutHour()
													* productPrice.getPrice());
										}
									}
								} else if (productPriceType == ProductPrice.HOUR_METHOD) {
									if (i == 0) {
										chessDto.setQty(getHour(
												chessDto.getStartTime(),
												chessDto.getEndTime(),
												product.getMin_of_buff()));
									}

									if (productPrice.getSeq() == 1
											&& productPrice
													.getTake_eff_end_time() == null) {
										// 说明全部时间都是按小时算，计算后直接退出
										chessDto.setTotalPrice(chessDto
												.getQty()
												* productPrice.getPrice());
										chessDto.setVipPrice(chessDto.getQty()
												* productPrice.getVip_price());
										chessDto.setActualPrice(chessDto
												.getQty()
												* productPrice.getPrice());
									} else {
										if (productPrice.getSeq() == 1) {
											if (chessDto.getQty().intValue() > 0) {
												int time = chessDto.getQty() < Integer
														.parseInt(productPrice
																.getTake_eff_end_time()) ? Integer
														.parseInt(productPrice
																.getTake_eff_end_time())
														: chessDto.getQty();
												chessDto.setTotalPrice(time
														* productPrice
																.getPrice());
												chessDto.setVipPrice(time
														* productPrice
																.getVip_price());
												chessDto.setActualPrice(time
														* productPrice
																.getPrice());
											}
											if (chessDto.getQty() < Integer
													.parseInt(productPrice
															.getTake_eff_end_time()))
												break;
											else
												tempTime = chessDto.getQty()
														- Integer
																.parseInt(productPrice
																		.getTake_eff_end_time());
										} else {

											chessDto.setTotalPrice(chessDto
													.getTotalPrice()
													+ tempTime
													* productPrice.getPrice());
											chessDto.setVipPrice(chessDto
													.getVipPrice()
													+ tempTime
													* productPrice
															.getVip_price());
											chessDto.setActualPrice(chessDto
													.getActualPrice()
													+ tempTime
													* productPrice.getPrice());
										}
									}
								}
							}
						} else {
							// 直接用product中的价格来进行计算
							chessDto.setQty(getHour(chessDto.getStartTime(),
									chessDto.getEndTime(),
									product.getMin_of_buff()));
							chessDto.setTotalPrice(chessDto.getQty()
									* product.getPrice());
							chessDto.setVipPrice(chessDto.getQty()
									* product.getVip_price());
							chessDto.setActualPrice(chessDto.getQty()
									* product.getPrice());
						}
					}
				}
			}
		}
	}

	/**
	 * 计算其它类消 费的总价、实际价
	 * 
	 * @param otherList
	 * @throws Exception
	 */
	public void calcOtherPrice(List otherList) throws Exception {
		if (otherList != null && !otherList.isEmpty()) {
			for (Iterator its = otherList.iterator(); its.hasNext();) {
				BizBillingItemDto dto = (BizBillingItemDto) its.next();

				DtaProduct product = dao.getProductByNo(dto.getProductNo());

				if (!dto.getStatus().equals(BizBillingItem.STATUS_CANCEL)) {
					dto.setTotalPrice(dto.getQty() * product.getPrice());
					dto.setVipPrice(dto.getQty() * product.getVip_price());
					dto.setActualPrice(dto.getTotalPrice());
				} else {
					dto.setTotalPrice(0);
					dto.setVipPrice(0);
					dto.setActualPrice(0);
				}
			}
		}
	}

	/**
	 * 求价格总和
	 * 
	 * @param serviceList
	 * @param chessList
	 * @param otherList
	 * @return
	 * @throws Exception
	 */
	@Override
	public BillingPrice sum(List serviceList, List chessList, List otherList)
			throws Exception {
		int totalPrice = 0, vipPrice = 0, actualPrice = 0;

		if (serviceList != null && !serviceList.isEmpty()) {
			for (Iterator its = serviceList.iterator(); its.hasNext();) {
				BizBillingServiceItemDto dto = (BizBillingServiceItemDto) its
						.next();
				totalPrice += dto.getTotalPrice();
				vipPrice += dto.getVipPrice();
				actualPrice += dto.getActualPrice();
			}
		}

		if (chessList != null && !chessList.isEmpty()) {
			for (Iterator its = chessList.iterator(); its.hasNext();) {
				BizBillingChessItemDto dto = (BizBillingChessItemDto) its
						.next();
				totalPrice += dto.getTotalPrice();
				vipPrice += dto.getVipPrice();
				actualPrice += dto.getActualPrice();
			}
		}

		if (otherList != null && !otherList.isEmpty()) {
			for (Iterator its = otherList.iterator(); its.hasNext();) {
				BizBillingItemDto dto = (BizBillingItemDto) its.next();
				totalPrice += dto.getTotalPrice();
				vipPrice += dto.getVipPrice();
				actualPrice += dto.getActualPrice();
			}
		}

		BillingPrice price = new BillingPrice(totalPrice, vipPrice, actualPrice);
		return price;
	}

	/**
	 * 批量判断服务类、棋牌类是否都已是结束状态
	 * 
	 * @param serviceList
	 * @param chessList
	 * @return 有未结束状态返回false，其余返回true
	 * @throws Exception
	 */
	@Override
	public boolean batchEndStatus(List serviceList, List chessList)
			throws Exception {
		boolean flag = true;

		if (serviceList != null && !serviceList.isEmpty()) {
			for (Iterator its = serviceList.iterator(); its.hasNext();) {
				BizBillingServiceItemDto dto = (BizBillingServiceItemDto) its
						.next();
				if (!(dto.getStatus().equals(BizBillingItem.STATUS_END) || dto
						.getStatus().equals(BizBillingItem.STATUS_CANCEL))) {
					flag = false;
					break;
				}
			}
		}

		if (flag) {
			if (chessList != null && !chessList.isEmpty()) {
				for (Iterator its = chessList.iterator(); its.hasNext();) {
					BizBillingChessItemDto dto = (BizBillingChessItemDto) its
							.next();
					if (!(dto.getStatus().equals(BizBillingItem.STATUS_END) || dto
							.getStatus().equals(BizBillingItem.STATUS_CANCEL))) {
						flag = false;
						break;
					}
				}
			}
		}

		return flag;
	}

	/**
	 * 根据帐单编号构造虚拟的LIST，以便于进行消费查询
	 * 
	 * @param billingIds
	 *            格式：id;id
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<BizBilling> constructBizBillingList(String billingIds)
			throws Exception {
		String[] billingIdArray = billingIds.split(";");
		List<BizBilling> list = new ArrayList<BizBilling>();
		for (String billingId : billingIdArray) {
			BizBilling billing = new BizBilling();
			billing.setId(Integer.parseInt(billingId));
			list.add(billing);
		}
		return list;
	}

	/**
	 * 根据折扣/赠送重新再次计价
	 * 
	 * @param serviceList
	 * @param chessList
	 * @param otherList
	 *            备注：billingItems格式:module;itemId;isFree;isDiscount;
	 *            discountRange;actualPrice;
	 */
	@Override
	public void calcPrice(List serviceList, List chessList, List otherList,
			String[] billingItems) throws Exception {
		if (billingItems == null || billingItems.length <= 0)
			return;

		for (String item : billingItems) {
			String[] items = item.split(";");

			if (items[0].equals("service")) {
				for (Iterator its = serviceList.iterator(); its.hasNext();) {
					BizBillingServiceItemDto dto = (BizBillingServiceItemDto) its
							.next();
					if (dto.getId().intValue() == Integer.parseInt(items[1])) {
						dto.setIs_free(items[2]);
						dto.setIs_discount(items[3]);
						dto.setDiscount_range(Integer.parseInt(items[4]));
						if (items[2].equals("Y")) {
							dto.setActualPrice(Integer.parseInt(items[5]));
						}
						if (items[3].equals("Y")) {
							if (dto.getTotalPrice()
									* Integer.parseInt(items[4]) / 100 == Integer
										.parseInt(items[5])) {
								dto.setActualPrice(Integer.parseInt(items[5]));
							} else
								dto.setActualPrice(dto.getTotalPrice()
										* Integer.parseInt(items[4]) / 100);
						}
						break;
					}
				}
			} else if (items[0].equals("chess")) {
				for (Iterator its = chessList.iterator(); its.hasNext();) {
					BizBillingChessItemDto dto = (BizBillingChessItemDto) its
							.next();
					if (dto.getId().intValue() == Integer.parseInt(items[1])) {
						dto.setIs_free(items[2]);
						dto.setIs_discount(items[3]);
						dto.setDiscount_range(Integer.parseInt(items[4]));
						if (items[2].equals("Y")) {
							dto.setActualPrice(Integer.parseInt(items[5]));
						}
						if (items[3].equals("Y")) {
							if (dto.getTotalPrice()
									* Integer.parseInt(items[4]) / 100 == Integer
										.parseInt(items[5])) {
								dto.setActualPrice(Integer.parseInt(items[5]));
							} else
								dto.setActualPrice(dto.getTotalPrice()
										* Integer.parseInt(items[4]) / 100);
						}
						break;
					}
				}

			} else if (items[0].equals("other")) {
				for (Iterator its = otherList.iterator(); its.hasNext();) {
					BizBillingItemDto dto = (BizBillingItemDto) its.next();
					if (dto.getId().intValue() == Integer.parseInt(items[1])) {
						dto.setIs_free(items[2]);
						dto.setIs_discount(items[3]);
						dto.setDiscount_range(Integer.parseInt(items[4]));
						if (items[2].equals("Y")) {
							dto.setActualPrice(Integer.parseInt(items[5]));
						}
						if (items[3].equals("Y")) {
							if (dto.getTotalPrice()
									* Integer.parseInt(items[4]) / 100 == Integer
										.parseInt(items[5])) {
								dto.setActualPrice(Integer.parseInt(items[5]));
							} else
								dto.setActualPrice(dto.getTotalPrice()
										* Integer.parseInt(items[4]) / 100);
						}
						break;
					}
				}
			}
		}
	}

	/**
	 * 根据帐单ID更新手牌和房间状态
	 */
	@Override
	public void updateTokenOrRoomStatus(String billingIds, String staffNo)
			throws Exception {
		String[] billingIdArray = billingIds.split(";");

		for (String billingId : billingIdArray) {
			List relatedItemList = dao
					.findBizBillingRelatedItemListByBillingId(billingId);
			if (relatedItemList != null && !relatedItemList.isEmpty()) {
				for (Iterator its = relatedItemList.iterator(); its.hasNext();) {
					BizBillingRelatedItem relatedItem = (BizBillingRelatedItem) its
							.next();
					if (relatedItem.getItem_type().intValue() == BizBillingRelatedItem.ITEM_TYPE_ROOM) {
						dao.updateRoomStatusByBillingId(Room.ROOM_STATUS_FREE,
								relatedItem.getBilling_id(), staffNo);
					} else if (relatedItem.getItem_type().intValue() == BizBillingRelatedItem.ITEM_TYPE_TOKEN) {
						dao.updateTokenStatusByBillingId(
								DtaToken.TOKEN_STATUS_FREE,
								relatedItem.getBilling_id(), staffNo);
					}
				}
			}
		}
	}

	/**
	 * 支付 (1.更新biz_billing 2.更新biz_billing_item 3.更新biz_billed 4.更新
	 * biz_billed_payment 5.如果是会员:dta_vip_account,(金额及积分） 4.释放手牌、房间及技师状态
	 * 
	 * @param paymentType
	 * @param billingPrice
	 * @param actualAmount
	 * @param returnAmount
	 * @param vipCard
	 * @param billingList
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void addPay(String paymentType,
			ConsultBillingServiceImpl.BillingPrice billingPrice,
			Integer actualAmount, Integer returnAmount, String vipCard,
			List billingList, List serviceList, List chessList, List otherList,
			String staffNo) throws Exception {
		// 1.更新帐户表
		String billingIds = "";
		for (Iterator its = billingList.iterator(); its.hasNext();) {
			BizBilling billing = (BizBilling) its.next();
			billingIds += billing.getId() + ";";
			dao.updateBizBillingStatusByBillingId(BizBilling.STATUS_PAID,
					billing.getId(), staffNo);
		}

		// 2.更新biz_billed表
		BizBilled billed = new BizBilled();
		billed.setBilled_no(billingIds.substring(0, billingIds.length() - 1));
		billed.setCash_staff_no(staffNo);
		billed.setTotal_amount(billingPrice.getTotalPrice());
		if (vipCard != null && vipCard.length() > 0) {
			billed.setVip_no(vipCard);
			billed.setAmount_after_discount(billingPrice.getVipPrice());
		} else
			billed.setAmount_after_discount(billingPrice.getActualPrice());
		billed.setReceive_amount(actualAmount);
		billed.setReturn_amount(returnAmount);
		billed.setTotal_vip_point(billed.getAmount_after_discount());
		billed.setCrt_user(staffNo);
		dao.addBizBilled(billed);

		// 3.处理biz_billing_item
		BizBillingItem billingItem = null;
		if (serviceList != null && !serviceList.isEmpty()) {
			for (Iterator its = serviceList.iterator(); its.hasNext();) {
				BizBillingServiceItemDto dto = (BizBillingServiceItemDto) its
						.next();
				billingItem = new BizBillingItem();
				billingItem.setId(dto.getId());
				billingItem.setVip_product_price(dto.getVipPrice());
				billingItem.setProduct_name(dto.getProductName());
				billingItem.setVip_point(dto.getVipPrice());
				billingItem.setActual_price(dto.getActualPrice());
				billingItem.setPercent_off(dto.getDiscount_range());
				billingItem.setIs_discount(dto.getIs_discount());
				billingItem.setIs_free(dto.getIs_free());
				billingItem.setQty(dto.getQty());
				billingItem.setBilled_id(billed.getId());
				billingItem.setMod_user(staffNo);
				dao.updateBizBillingItemInfo(billingItem);
			}
		}
		if (chessList != null && !chessList.isEmpty()) {
			for (Iterator its = chessList.iterator(); its.hasNext();) {
				BizBillingChessItemDto dto = (BizBillingChessItemDto) its
						.next();
				billingItem = new BizBillingItem();
				billingItem.setId(dto.getId());
				billingItem.setVip_product_price(dto.getVipPrice());
				billingItem.setProduct_name(dto.getProductName());
				billingItem.setVip_point(dto.getVipPrice());
				billingItem.setActual_price(dto.getActualPrice());
				billingItem.setPercent_off(dto.getDiscount_range());
				billingItem.setIs_discount(dto.getIs_discount());
				billingItem.setIs_free(dto.getIs_free());
				billingItem.setQty(dto.getQty());
				billingItem.setBilled_id(billed.getId());
				billingItem.setMod_user(staffNo);
				dao.updateBizBillingItemInfo(billingItem);
			}
		}
		if (otherList != null && !otherList.isEmpty()) {
			for (Iterator its = otherList.iterator(); its.hasNext();) {
				BizBillingItemDto dto = (BizBillingItemDto) its.next();
				billingItem = new BizBillingItem();
				billingItem.setId(dto.getId());
				billingItem.setVip_product_price(dto.getVipPrice());
				billingItem.setProduct_name(dto.getProductName());
				billingItem.setVip_point(dto.getVipPrice());
				billingItem.setActual_price(dto.getActualPrice());
				billingItem.setPercent_off(dto.getDiscount_range());
				billingItem.setIs_discount(dto.getIs_discount());
				billingItem.setIs_free(dto.getIs_free());
				billingItem.setQty(dto.getQty());
				billingItem.setBilled_id(billed.getId());
				billingItem.setMod_user(staffNo);
				dao.updateBizBillingItemInfo(billingItem);
			}
		}

		// 4.更新biz_billed_payment
		BizBilledPayment billedPayment = new BizBilledPayment();
		billedPayment.setBilled_id(billed.getId());
		billedPayment.setPayment_type(paymentType);
		billedPayment.setPayment_amount(billingPrice.getActualPrice());
		dao.addBizBilledPayment(billedPayment);

		// 5.更新dta_vip_accountge

		VipAccount vip = dao.getVipAccount(vipCard);
		if (paymentType.equals(BizBilledPayment.PAYMENTTYPE_MEMBERCARD))
			vip.setCurr_vip_amount(vip.getCurr_vip_amount()
					- billed.getAmount_after_discount());
		if (vipCard != null && vipCard.length() > 0) {
			vip.setTotal_vip_point(vip.getTotal_vip_point()
					+ billed.getTotal_vip_point());
			dao.updateVipAccount(vipCard, vip.getCurr_vip_amount(),
					vip.getTotal_vip_point(), staffNo);
		}

	}

	// 价格对象类
	public class BillingPrice {
		private Integer totalPrice;
		private Integer vipPrice;
		private Integer actualPrice;

		public BillingPrice(Integer totalPrice, Integer vipPrice,
				Integer actualPrice) {
			super();
			this.totalPrice = totalPrice;
			this.vipPrice = vipPrice;
			this.actualPrice = actualPrice;
		}

		public Integer getTotalPrice() {
			return totalPrice;
		}

		public void setTotalPrice(Integer totalPrice) {
			this.totalPrice = totalPrice;
		}

		public Integer getVipPrice() {
			return vipPrice;
		}

		public void setVipPrice(Integer vipPrice) {
			this.vipPrice = vipPrice;
		}

		public Integer getActualPrice() {
			return actualPrice;
		}

		public void setActualPrice(Integer actualPrice) {
			this.actualPrice = actualPrice;
		}
	}

	@Override
	public BizBilling findBillingByToken(String tokenNo) throws Exception {
		return this.dao.findBillingByTokenNo(tokenNo);
	}

	@Override
	public BizBilling findBillingById(String billingId) throws Exception {
		return this.dao.findBillingById(billingId);
	}

	@Override
	public List<BizBillingItem> findBillingItemByBillingId(String billingId)
			throws Exception {
		return this.dao.findBillingItemByBillingId(billingId);
	}

	@Override
	public void startProduct(Integer billingItemId, String tokenNo,
			Integer[] serviceIds, String[] workerNos, String[] turnTypes,
			String[] callTurnWorkerNos, SysAccount account) throws Exception {
		BizBillingItem billingItem = this.dao
				.getBizBillingItemByItemId(billingItemId);
		DtaProduct product = this.dao.findProductByItemId(billingItemId);
		Date sdate = new Date();
		billingItem.setStart_time(sdate);
		Date edate = new Date(product.getLen_of_min() * 60L * 1000
				+ sdate.getTime());
		billingItem.setPlan_end_time(edate);
		billingItem.setServe_status(BizBillingItem.BILLING_ITEM_SERVE_STATUS_SERVING);
		CommonUtils.setUpCrtMode(billingItem, account);
		this.dao.updateByFull(billingItem);
		for (int i = 0; i < serviceIds.length; i++) {
			Integer serviceId = serviceIds[i];
			String workerNo = workerNos[i];
			String turnType = turnTypes[i];
			DtaWorker worker = (DtaWorker) CommonUtils.queryOne(this.dao.queryByProp(
					DtaWorker.class, "worker_no", workerNo));
			if (!DtaWorker.STATUS_FREE.equals(worker.getStatus())) {
				throw new RuntimeException("技师已经被分配，请选择其他技师.");
			}
			BizBillingService bbs = (BizBillingService) this.dao.queryById(
					BizBillingService.class, serviceId);
			bbs.setWorker_no(workerNo);
			if (callTurnWorkerNos != null && callTurnWorkerNos.length > 0) {
				String callTurnWorkerNo = callTurnWorkerNos[i];
				bbs.setCall_turn_worker_no(callTurnWorkerNo);
			}
			bbs.setTurn_type(turnType);
			this.dao.updateByFull(bbs);
		}
	}
}
